import datetime
import os
from flask import Flask, render_template, request, send_from_directory, flash, abort
from scores_source.gaokao_data_process import GaokaoData2025, GaokaoDataSeniorOne, GaokaoDataProcess, GetInfoFromId, \
    ExamRoom, CatalogueCourses, ExamInvigilators, JuniorExam
from scores_source.gaokao_logging import MyException

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', '5e6ca24a28a0494f89deac1e3f05bb8f')

root_dir = '/data/results'
subject_assessment = '学科评价含义：A：单科上线与总分上线匹配较好；B：单科优势或单科冒进 C：单科滞后；D：单科上线与总分上线匹配不好 E：学科上线人数 ＜ 总分上线人数的 80%；F或无数据：总分上线人数为零或没有选学该学科'


def get_date_weekday():
    today = datetime.datetime.now()
    date = today.strftime('%Y年%m月%d日')
    week_name = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
    week_day = week_name[today.weekday()]
    return f'{date} {week_day}'


def format_two_decimals(number):
    if isinstance(number, (int, float)):
        return "{:.2f}".format(number)


def data_update():
    return datetime.datetime.today().strftime('%Y年%m月%d日 %H点%M分%S秒')


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'xls', 'xlsx', 'csv'}  # 允许的文件类型


@app.route('/')
def instructions():
    return render_template('instructions.html', weekday=get_date_weekday())


@app.route('/index/', methods=['GET', 'POST'])
def process_by_ratio():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('index.html',
                               update_time=update_time,
                               weekday=weekday)
    else:
        path_file = request.files.get('path_file')
        history_ratio = request.form.get('history_ratio')
        physics_ratio = request.form.get('physics_ratio')
        flag = request.form.get('flag')

        try:
            # 创建对象
            exam = GaokaoData2025(path_file)
            GaokaoData2025.flag = eval(flag)
            MyException(exam)
            # 从前端GET的上线比例转换成小数，赋值给两个类变量history_line_ratio和physics_line_ratio
            GaokaoData2025.history_line_ratio = float(history_ratio)
            GaokaoData2025.physics_line_ratio = float(physics_ratio)

            # 从后端获取下载excel表，各科平均分，有效分，错位人数及学科评价等数据
            final_excel_file, av_history, av_physics, good_history, good_physics = exam.excel_school_files()
            # 历史类平均分生成html
            av_history.reset_index(inplace=True)
            # av_history[['政治赋分', '地理赋分', '生物赋分']].map(lambda x: format(x, '.2f'))
            av_history_html = av_history.to_html(index=False, classes=['table', 'table-bordered', 'table-striped'],
                                                 na_rep='')
            # 物理类平均分生成html
            av_physics.reset_index(inplace=True)
            av_physics_html = av_physics.to_html(index=False, classes=['table', 'table-bordered', 'table-striped'],
                                                 na_rep='')
            # 历史类有效分统计生成html
            df_history_html = good_history.to_html(index=True, classes=['table', 'table-bordered', 'table-striped'],
                                                   na_rep='')
            # 物理尖有效分统计生成html
            df_physics_html = good_physics.to_html(index=True, classes=['table', 'table-bordered', 'table-striped'],
                                                   na_rep='')

            return render_template('index.html',
                                   weekday=weekday,
                                   update_time=update_time,
                                   av_history_html=av_history_html,
                                   av_physics_html=av_physics_html,
                                   df_history_html=df_history_html,
                                   df_physics_html=df_physics_html,
                                   path_file=path_file,
                                   history_ratio=format(float(history_ratio), '.0%'),
                                   physics_ratio=format(float(physics_ratio), '.0%'),
                                   final_excel_file=final_excel_file,
                                   subject_assessment=subject_assessment)
        except Exception as e:
            flash(
                f'{e}\n请检查工作表上是否有“总表”，成绩表上列名是否符合要求，成绩表内是否有“缺考”，“-”等非数字类的无效字符！！！')
            return render_template('index.html',
                                   update_time=update_time,
                                   weekday=weekday)


@app.route('/index/<filename>')
def download_by_ratio(filename):
    """
    获取下载excel文件视图函数
    :param filename: final_excel_file
    :return: 从目录下载文件路径
    """
    return send_from_directory(root_dir, filename)


@app.route('/full_subjects/', methods=['GET', 'POST'])
def full_subjects():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('full_subjects.html', weekday=weekday, update_time=update_time)
    else:
        path_file = request.files.get('path_file')
        line_ratio = request.form.get('line_ratio')
        flag = request.form.get('flag')
        try:
            exam = GaokaoDataSeniorOne(path_file)
            MyException(exam)
            GaokaoData2025.flag = eval(flag)
            GaokaoDataSeniorOne.line_ratio = float(line_ratio)
            excel_file_name, av_df, good_df = exam.excel_school_senior_one_files()
            av_df.reset_index(inplace=True)
            av_html = av_df.to_html(index=False, classes=['table', 'table-bordered', 'table-striped'], na_rep='')
            good_html = good_df.to_html(index=True, classes=['table', 'table-bordered', 'table-striped'], na_rep='')
            return render_template('full_subjects.html',
                                   weekday=weekday,
                                   update_time=update_time,
                                   av_html=av_html,
                                   good_html=good_html,
                                   path_file=path_file,
                                   line_ratio=format(float(line_ratio), '.0%'),
                                   excel_file_name=excel_file_name,
                                   subject_assessment=subject_assessment)
        except Exception as e:
            flash(
                f'{e}\n请检查工作表上是否有“总表”，成绩表上列名是否符合要求，成绩表内是否有“缺考”，“-”等非数字类的无效字符！！！')
            return render_template('full_subjects.html', weekday=weekday, update_time=update_time)


@app.route('/full_subjects/<filename>')
def download_by_full_subjects(filename):
    return send_from_directory(root_dir, filename)


@app.route('/scores/<filename>')
def download_by_good_scores(filename):
    return send_from_directory(root_dir, filename)


@app.route('/scores/', methods=['GET', 'POST'])
def process_by_good_scores():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('scores.html',
                               update_time=update_time, weekday=weekday)
    else:
        path_file = request.files.get('path_file')
        h_chinese = request.form.get('h_chinese')
        h_math = request.form.get('h_math')
        h_english = request.form.get('h_english')
        h_history = request.form.get('h_history')
        h_politics = request.form.get('h_politics')
        h_geography = request.form.get('h_geography')
        h_biology = request.form.get('h_biology')
        h_total = request.form.get('h_total')

        p_chinese = request.form.get('p_chinese')
        p_math = request.form.get('p_math')
        p_english = request.form.get('p_english')
        p_physics = request.form.get('p_physics')
        p_chemistry = request.form.get('p_chemistry')
        p_politics = request.form.get('p_politics')
        p_geography = request.form.get('p_geography')
        p_biology = request.form.get('p_biology')
        p_total = request.form.get('p_total')
        try:
            exam = GaokaoDataProcess(path_file)
            MyException(exam)
            # 物理类各科有效分
            GaokaoDataProcess.subjects_good_scores_physics = {'语文': float(p_chinese), '数学': float(p_math),
                                                              '英语': float(p_english),
                                                              '物理': float(p_physics), '政治': float(p_politics),
                                                              '地理': float(p_geography), '化学': float(p_chemistry),
                                                              '生物': float(p_biology),
                                                              '总分': float(p_total)}
            # 历史类各科有效分
            GaokaoDataProcess.subjects_good_scores_history = {'语文': float(h_chinese), '数学': float(h_math),
                                                              '英语': float(h_english),
                                                              '历史': float(h_history), '政治': float(h_politics),
                                                              '地理': float(h_geography),
                                                              '生物': float(h_biology), '总分': float(h_total)}
            # 获取后端处理的数据
            excel_file_name, good_physics, good_history = exam.excel_files()
            # 多重索引排序，确保在前端按班级顺序展示数据
            good_history.sort_index(level=0, inplace=True, ascending=True)
            good_physics.sort_index(level=0, inplace=True, ascending=True)
            # 生成html用于前端展示
            good_history_html = good_history.to_html(index=True, classes=['table', 'table-bordered', 'table-striped'],
                                                     na_rep='')
            good_physics_html = good_physics.to_html(classes=['table', 'table-bordered', 'table-striped'], na_rep='')

            return render_template('scores.html',
                                   weekday=weekday,
                                   update_time=update_time,
                                   good_history_html=good_history_html,
                                   good_physics_html=good_physics_html,
                                   path_file=path_file,
                                   h_total=h_total,
                                   p_total=p_total,
                                   excel_file_name=excel_file_name)
        except Exception as e:
            flash(
                f'{e}\n请检查工作表上是否有“总表”，成绩表上列名是否符合要求，成绩表内是否有“缺考”，“-”等非数字类的无效字符！！！')
            return render_template('scores.html',
                                   update_time=update_time, weekday=weekday)


@app.route('/exams/', methods=['GET', 'POST'])
def exams():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('exams.html', weekday=weekday, update_time=update_time)
    else:
        path_file = request.files.get('path_file')
        number_in_room = request.form.get('number_in_room')
        try:
            exam_rooms = ExamRoom(path_file)
            MyException(exam_rooms)
            ExamRoom.num_in_room = int(number_in_room)
            exams_info_excel = exam_rooms.exam_room_choice()
            return render_template('exams.html',
                                   weekday=weekday,
                                   update_time=update_time,
                                   path_file=path_file,
                                   number_in_room=number_in_room,
                                   exams_info_excel=exams_info_excel)
        except Exception as e:
            flash(
                f'{e}\n请检查工作表上是否有“总表”，成绩表上列名是否符合要求，成绩表内是否有“缺考”，“-”等非数字类的无效字符！！！')
            return render_template('exams.html',
                                   update_time=update_time, weekday=weekday)


@app.route('/exams/<filename>')
def download_by_exams(filename):
    return send_from_directory(root_dir, filename)


@app.route('/invigilation/', methods=['GET', 'POST'])
def invigilation():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('invigilation.html', weekday=weekday, update_time=update_time)
    else:
        path_file = request.files.get('path_file')
        exam_numbers = request.form.get('exam_numbers')
        room_numbers = request.form.get('room_numbers')
        try:
            exam = ExamInvigilators(path_file)
            MyException(exam)
            ExamInvigilators.room_numbers = int(room_numbers)
            ExamInvigilators.exam_numbers = int(exam_numbers)
            invigilator_table = exam.invigilation_table()
            invigilation_html = invigilator_table.to_html(index=True,
                                                          classes=['table', 'table-bordered', 'table-striped'],
                                                          na_rep='')
            invigilators = exam.exam_teachers()
            return render_template('invigilation.html',
                                   invigilation_html=invigilation_html,
                                   invigilators=invigilators,
                                   path_file=path_file,
                                   exam_numbers=exam_numbers,
                                   room_numbers=room_numbers,
                                   update_time=update_time,
                                   weekday=weekday)
        except Exception as e:
            flash(
                f'{e}\n请检查工作表上是否有“总表”，成绩表上列名是否符合要求，成绩表内是否有“缺考”，“-”等非数字类的无效字符！！！')
            return render_template('invigilation.html',
                                   update_time=update_time,
                                   weekday=weekday)


@app.route('/junior/', methods=['GET', 'POST'])
def junior():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('junior.html', weekday=weekday, update_time=update_time)
    else:
        path_file = request.files.get('path_file')
        good_scores = request.form.get('good_scores')
        try:
            junior_exam = JuniorExam(path_file)
            MyException(junior_exam)
            junior_scores = junior_exam.junior_scores()
            junior_av = junior_exam.get_av()
            junior_scores_html = junior_scores.to_html(index=False,
                                                       classes=['table', 'table-bordered', 'table-striped'], na_rep='')
            junior_av_html = junior_av.to_html(index=False, classes=['table', 'table-bordered', 'table-striped'],
                                               na_rep='')
            junior_goodscores = junior_exam.goodscore_process(float(good_scores))
            goodscore_html = junior_goodscores.to_html(index=True, classes=['table', 'table-bordered', 'table-striped'],
                                                       na_rep='')
            final_excel_file = junior_exam.concat_results(float(good_scores))
            return render_template('junior.html',
                                   weekday=weekday,
                                   update_time=update_time,
                                   junior_scores_html=junior_scores_html,
                                   junior_av_html=junior_av_html,
                                   path_file=path_file,
                                   goodscore_html=goodscore_html,
                                   final_excel_file=final_excel_file)
        except Exception:
            return render_template('junior.html',
                                   update_time=update_time, weekday=weekday)


@app.route('/junior/<filename>')
def junior_download(filename):
    return send_from_directory(root_dir, filename)


@app.route('/invigilation/<filename>')
def invigilation_download(filename):
    return send_from_directory(root_dir, filename)


@app.route('/catalog/', methods=['GET', 'POST'])
def catalog_courses():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('catalogue_courses.html', weekday=weekday, update_time=update_time)
    else:
        path_file = request.files.get('path_file')
        try:
            catalog = CatalogueCourses(path_file)
            MyException(catalog)
            catalog_table = catalog.statistics_for_courses()
            catalog_html = catalog_table.to_html(index=False, classes=['table', 'table-bordered', 'table-striped'],
                                                 na_rep='')
            catalog_exported = catalog.split_by_subject()
            return render_template('catalogue_courses.html',
                                   catalog_html=catalog_html,
                                   update_time=update_time,
                                   weekday=weekday,
                                   path_file=path_file,
                                   catalog_exported=catalog_exported)
        except Exception as e:
            flash(
                f'{e}\n请检查工作表上是否有“总表”，成绩表上列名是否符合要求，成绩表内是否有“缺考”，“-”等非数字类的无效字符！！！')
            return render_template('catalogue_courses.html', update_time=update_time, weekday=weekday)


@app.route('/catalog/<filename>')
def catalog_download(filename):
    return send_from_directory(root_dir, filename)


@app.route('/get_info/', methods=['GET', 'POST'])
def get_info():
    weekday = get_date_weekday()
    update_time = data_update()
    if request.method == 'GET':
        return render_template('get_info_from_id.html', update_time=update_time, weekday=weekday)
    else:
        path_file = request.files.get('path_file')
        try:
            id_info = GetInfoFromId(path_file)
            MyException(id_info)
            id_matched, bad_df, id_bad, show_data = id_info.get_sex_birth_age()
            bad_df_html = bad_df.to_html(index=False,
                                         classes=['table', 'table-bordered', 'table-striped'],
                                         formatters={
                                             'text-align': 'center',
                                             'color': 'red'
                                         },
                                         na_rep='')
            show_data_html = show_data.to_html(index=False, classes=['table', 'table-bordered', 'table-striped'],
                                               formatters={
                                                   'text-align': 'center'
                                               })
            return render_template('get_info_from_id.html',
                                   bad_df=bad_df,
                                   id_matched=id_matched,
                                   bad_df_html=bad_df_html,
                                   id_bad=id_bad,
                                   update_time=update_time,
                                   weekday=weekday,
                                   path_file=path_file,
                                   show_data_html=show_data_html)
        except Exception as e:
            flash(f'{e}')
            return render_template('get_info_from_id.html', update_time=update_time, weekday=weekday)


@app.route('/get_info/<filename>')
def id_info_download(filename):
    return send_from_directory(root_dir, filename)


if __name__ == '__main__':
    app.run()
